﻿package {
	/* Our framework */
    import org.flixel.*;
	
	/*
	 * The heart of the game, here all classes are involved into 
	 * a rules of the game, defining the damage, who beat who, the 
	 * rules to combat and survive, the rules to create enemies, 
	 * the environment and others stuffs.
	 */
    public class StatePlay extends FlxState	{
		
		/* References the player, the shot and all stuff about him */
        private var _player:Player = new Player(0, FlxG.height/2);
		private var _shot:FlxGroup = new FlxGroup();
		private var _blast:FlxGroup = new FlxGroup();
		private var _multiplyer:uint = 0;
		public function get player():Player { return _player; }
		public function get shot():FlxGroup { return _shot; }
		public function get blast():FlxGroup { return _blast; }
		
		/* Enemy stuff */
		private var _enemy:FlxGroup = new FlxGroup();
		private var _blast_frag:FlxGroup = new FlxGroup();		
		private var _cannon:FlxGroup = new FlxGroup();
		private var _enemy_spawner:Spawner = new Spawner(_enemy);
		public function get enemy():FlxGroup { return _enemy; } 
		public function	get blast_frag():FlxGroup { return _blast_frag; } 
		public function get cannon():FlxGroup { return _cannon; }
		public function get enemy_spawner():Spawner { return _enemy_spawner; }
		
		/* References the HUD, all info about the game*/
        private var _hud:HUD = new HUD();
		public function get hud():HUD { return _hud; }
		
		/* Environment and level details */
        private var _environment:Environment = new Environment();
        private var _scene:FlxGroup = new FlxGroup();
		public function get scene():FlxGroup { return _scene; }
		
		/* Create all stuff and insert into state */
        override public function create():void {
            add(_scene);
            add(_player);
            add(_shot);
            add(_blast);
            add(_enemy);
			add(_blast_frag);
			add(_cannon);

			/* Configure and the HUD */
            _hud.updateTries(_player.getTries());
            _hud.updateChargeBar(_player.getCharges());
            _hud.updateScore(0);
			FlxG.score = 0;
			_multiplyer = 0;
            add(_hud);

			/* Configure our spawner time and start */
			_enemy_spawner.create(0.5);
 			_enemy_spawner.start();

			/* Play music loop, and hides the mouse */
			FlxG.playMusic(Resources.music);
            FlxG.mouse.hide();
			
			/* Calls the parent */
            super.create();
        }
		
		/* Update and testing the collides */
        override public function update():void {
            testCollides();
            testPlayerHit();
            super.update();
        }

		/* Each collide test, pass function callback to treat */
        private function testCollides():void {
            FlxU.overlap(_shot, _enemy, doEnemyDamage);
            FlxU.overlap(_blast, _enemy, doEnemyBlast);
			FlxU.overlap(_blast_frag, _enemy, doBlastFrag);
            FlxU.overlap(_player, _enemy, doPlayerDamage);
			FlxU.overlap(_player, _cannon, doPlayerDamage);
        }

		/* Treat the enemy damage by single shot */
        private function doEnemyDamage(__shot:FlxObject, __enemy:FlxObject):void {
            __shot.kill();
            __enemy.hurt(1);
            FlxG.score++;
        }

		/* Treat the enemy damage by blast shot */
        private function doEnemyBlast(__shot:FlxObject, __enemy:FlxObject):void {
			__shot.kill();
            __enemy.hurt(10);
			FlxG.score += _multiplyer;
        }
		
		/* Theat the explosion of a enemy by the blast */
		private function doBlastFrag(__frag:FlxObject, __enemy:FlxObject):void {
			__frag.kill();
			__enemy.hurt(10);
			_multiplyer++;
		}

		/* Treat the damage on player */
        private function doPlayerDamage(__player:FlxObject, __enemy:FlxObject):void {
            __player.hurt(1);
            __enemy.hurt(1);
            _hud.updateTries(-1);
        }

		/* If player damage then dies */
        private function testPlayerHit():void {
            if(_player.dead) {
                FlxG.fade.start(0xff000000, 0.5, function():void {
                    FlxG.state = new StateGameOver();
                });
            }
        }

		/* Cleaning everything in memory */
        override public function destroy():void {
			_enemy_spawner.destroy();
            _player.destroy();
            _enemy.destroy();
            _shot.destroy();
            _blast.destroy();
            _hud.destroy();
            _environment.destroy();
            _scene.destroy();
			_blast_frag.destroy();
            super.destroy();
        }
    }
}
